package com.medsoft.perfstat.as;

import java.util.HashMap;
import java.util.Map;

import org.apache.commons.dbcp.BasicDataSource;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.beans.BeansException;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.config.ConstructorArgumentValues;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.stereotype.Service;

import com.cyl.kernel.DynamicDataSource;
import com.cyl.kernel.decript.Decript;
import com.cyl.kernel.util.Base64Util;
import com.medsoft.perfstat.dao.MetadataDAO;
import com.medsoft.perfstat.pojo.Apps;
@Service
public class MonitoredMySQLService implements InitializingBean,ApplicationContextAware,BeanPostProcessor {
	@Autowired
	private MetadataDAO metadataDAO;
	
	private ApplicationContext applicationContext;
    
	@Override
	public void afterPropertiesSet() throws Exception {
		Map<Object, Object> targetDataSources = new HashMap<Object, Object>();
		ConfigurableApplicationContext configurableApplicationContext = (ConfigurableApplicationContext) applicationContext;
	    // 获取bean工厂并转换为DefaultListableBeanFactory
	    DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) configurableApplicationContext.getBeanFactory();
	    for(Apps app : metadataDAO.queryApps("",0)) {
	    	RootBeanDefinition rbd = new RootBeanDefinition(BasicDataSource.class, AbstractBeanDefinition.AUTOWIRE_BY_NAME, true);
		    MutablePropertyValues propertyValues = new MutablePropertyValues();
		    propertyValues.add("url", "jdbc:mysql://" + app.getHostname() + ":" + app.getMapPort() + "/performance_schema?useUnicode=true&characterEncoding=gbk&autoReconnect=true&failOverReadOnly=false");
		    propertyValues.add("driverClassName", "com.mysql.jdbc.Driver");
		    propertyValues.add("username", app.getMysqlUsername());
		    propertyValues.add("password", Base64Util.getFromBase64(app.getMysqlPassword()));
		    propertyValues.add("maxActive", 5);
		    propertyValues.add("maxIdle", 5);
		    propertyValues.add("maxWait", 10000);
		    propertyValues.add("validationQuery", "select 1");
		    propertyValues.add("defaultAutoCommit", true);
		    propertyValues.add("connectionInitSqls", "");
		    rbd.setPropertyValues(propertyValues);
		    rbd.setDependencyCheck(AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);
		    beanFactory.registerBeanDefinition(app.getAppname() + "_ds", rbd);
		    targetDataSources.put(app.getAppname() + "_ds", applicationContext.getBean(app.getAppname() + "_ds"));
		}
	    RootBeanDefinition rbd = new RootBeanDefinition(DynamicDataSource.class, AbstractBeanDefinition.AUTOWIRE_BY_NAME, true);
	    MutablePropertyValues propertyValues = new MutablePropertyValues();
	    propertyValues.add("targetDataSources", targetDataSources);
	    rbd.setPropertyValues(propertyValues);
	    rbd.setDependencyCheck(AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);
	    beanFactory.registerBeanDefinition("targetDataSource", rbd);
	    
	    rbd = new RootBeanDefinition(SqlSessionFactoryBean.class, AbstractBeanDefinition.AUTOWIRE_BY_NAME, true);
	    propertyValues = new MutablePropertyValues();
	    propertyValues.add("configLocation", "classpath:conf/mybatis-config.xml");
	    propertyValues.add("mapperLocations", "classpath:conf/mybatis/mysql/perfstat_src*.xml");
	    propertyValues.add("dataSource", applicationContext.getBean("targetDataSource"));
	    rbd.setPropertyValues(propertyValues);
	    rbd.setDependencyCheck(AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);
	    beanFactory.registerBeanDefinition("sqlSessionFactoryTarget", rbd);
	    
	    propertyValues = new MutablePropertyValues();
	    ConstructorArgumentValues cargs = new ConstructorArgumentValues();
	    cargs.addIndexedArgumentValue(0, applicationContext.getBean("sqlSessionFactoryTarget"));
		rbd = new RootBeanDefinition(SqlSessionTemplate.class, cargs, propertyValues);
	    rbd.setDependencyCheck(AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);
	    beanFactory.registerBeanDefinition("sqlSessionTarget", rbd);
	}
	
	@Override
	public void setApplicationContext(ApplicationContext applicationContext)
			throws BeansException {
		this.applicationContext = applicationContext;
	}

	@Override
	public Object postProcessBeforeInitialization(Object bean, String beanName)
			throws BeansException {
		return bean;
	}

	@Override
	public Object postProcessAfterInitialization(Object bean, String beanName)
			throws BeansException {
		return bean;
	}
}
